﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.ExtensibleStorage;
using Autodesk.Revit.UI;
using YArchitech.ProgressBar;
using YArchitech.Revit;
using YJKRevitBase.WinForm;

namespace YJKRevitTextUtil
{
	internal class TextTool
	{
		public TextTool(ExternalCommandData cmdData)
		{
			this.m_doc = cmdData.Application.ActiveUIDocument.Document;
		}

		public List<Text> GetTextList(Element element)
		{
			List<Text> list = new List<Text>();
			TextNote textNote = element as TextNote;
			if (textNote != null)
			{
				TextNoteType textNoteType = textNote.TextNoteType;
				list.Add(new Text
				{
					Name = textNote.Text,
					Position = RevitElementExtension.GetTextNoteCoord(textNote),
					Font = textNoteType.get_Parameter(BuiltInParameter.TEXT_FONT).AsString(),
					Height = textNoteType.get_Parameter(BuiltInParameter.TEXT_SIZE).AsDouble() * 304.8,
					Color = Common.IntToRgbColor(textNoteType.get_Parameter(BuiltInParameter.LINE_COLOR).AsInteger()),
					Superscript = false,
					Subscript = false,
					Bold = Convert.ToBoolean(textNoteType.get_Parameter(BuiltInParameter.TEXT_STYLE_BOLD).AsInteger()),
					Italic = Convert.ToBoolean(textNoteType.get_Parameter(BuiltInParameter.TEXT_STYLE_ITALIC).AsInteger()),
					Underline = Convert.ToBoolean(textNoteType.get_Parameter(BuiltInParameter.TEXT_STYLE_UNDERLINE).AsInteger())
				});
				return list;
			}
			Group group = element as Group;
			if (group == null)
			{
				return null;
			}
			Schema schema = Schema.Lookup(Common.g_DataGuid);
			if (schema == null)
			{
				return null;
			}
			Entity entity = group.GetEntity(schema);
			if (entity == null)
			{
				return null;
			}
			Field field = schema.GetField("Id");
			IEnumerable<int> enumerable = entity.Get<IList<int>>(field);
			Field field2 = schema.GetField("Underline");
			IList<int> list2 = entity.Get<IList<int>>(field2);
			Field field3 = schema.GetField("Script");
			IDictionary<int, int> dictionary = entity.Get<IDictionary<int, int>>(field3);
			Field field4 = schema.GetField("Align");
			IDictionary<int, int> dictionary2 = entity.Get<IDictionary<int, int>>(field4);
			foreach (int num in enumerable)
			{
				ElementId elementId = new ElementId(num);
				TextNote textNote2 = this.m_doc.GetElement(elementId) as TextNote;
				TextNoteType textNoteType2 = textNote2.TextNoteType;
				list.Add(new Text
				{
					Name = textNote2.Text,
					Position = RevitElementExtension.GetTextNoteCoord(textNote2),
					Font = textNoteType2.get_Parameter(BuiltInParameter.TEXT_FONT).AsString(),
					Height = textNoteType2.get_Parameter(BuiltInParameter.TEXT_SIZE).AsDouble() * 304.8,
					Color = Common.IntToRgbColor(textNoteType2.get_Parameter(BuiltInParameter.LINE_COLOR).AsInteger()),
					Superscript = false,
					Subscript = false,
					Bold = Convert.ToBoolean(textNoteType2.get_Parameter(BuiltInParameter.TEXT_STYLE_BOLD).AsInteger()),
					Italic = Convert.ToBoolean(textNoteType2.get_Parameter(BuiltInParameter.TEXT_STYLE_ITALIC).AsInteger()),
					Underline = Convert.ToBoolean(textNoteType2.get_Parameter(BuiltInParameter.TEXT_STYLE_UNDERLINE).AsInteger())
				});
			}
			foreach (int index in list2)
			{
				list[index].Underline = true;
			}
			foreach (KeyValuePair<int, int> keyValuePair in dictionary)
			{
				if (1 == keyValuePair.Value)
				{
					list[keyValuePair.Key].Superscript = true;
				}
				else if (2 == keyValuePair.Value)
				{
					list[keyValuePair.Key].Subscript = true;
				}
			}
			foreach (KeyValuePair<int, int> keyValuePair2 in dictionary2)
			{
				list[keyValuePair2.Key].Alignment = keyValuePair2.Value;
			}
			return list;
		}

		public List<Text> GetTextListByGroup(Element element)
		{
			List<Text> list = new List<Text>();
			Group group = element as Group;
			if (group == null)
			{
				return null;
			}
			Schema schema = Schema.Lookup(Common.g_DataGuid);
			if (schema == null)
			{
				return null;
			}
			Entity entity = group.GetEntity(schema);
			if (entity == null || entity.Schema == null)
			{
				return null;
			}
			Field field = schema.GetField("Id");
			IEnumerable<int> enumerable = entity.Get<IList<int>>(field);
			Field field2 = schema.GetField("Underline");
			IList<int> list2 = entity.Get<IList<int>>(field2);
			Field field3 = schema.GetField("Script");
			IDictionary<int, int> dictionary = entity.Get<IDictionary<int, int>>(field3);
			Field field4 = schema.GetField("Align");
			IDictionary<int, int> dictionary2 = entity.Get<IDictionary<int, int>>(field4);
			Field field5 = schema.GetField("Orientation");
			XYZ position = entity.Get<XYZ>(field5, (Autodesk.Revit.DB.DisplayUnitType)3);
			foreach (int num in enumerable)
			{
				ElementId elementId = new ElementId(num);
				TextNote textNote = this.m_doc.GetElement(elementId) as TextNote;
				TextNoteType textNoteType = textNote.TextNoteType;
				string text = textNote.Text;
				int num2 = text.LastIndexOf("\r");
				if (text.Length > 1 && num2 == text.Length - 1)
				{
					text = text.Left(num2);
				}
				list.Add(new Text
				{
					Name = text,
					Position = RevitElementExtension.GetTextNoteCoord(textNote),
					Font = textNoteType.get_Parameter(BuiltInParameter.TEXT_FONT).AsString(),
					Height = textNoteType.get_Parameter(BuiltInParameter.TEXT_SIZE).AsDouble() * 304.8,
					Color = Common.IntToRgbColor(textNoteType.get_Parameter(BuiltInParameter.LINE_COLOR).AsInteger()),
					Superscript = false,
					Subscript = false,
					Bold = Convert.ToBoolean(textNoteType.get_Parameter(BuiltInParameter.TEXT_STYLE_BOLD).AsInteger()),
					Italic = Convert.ToBoolean(textNoteType.get_Parameter(BuiltInParameter.TEXT_STYLE_ITALIC).AsInteger()),
					Underline = Convert.ToBoolean(textNoteType.get_Parameter(BuiltInParameter.TEXT_STYLE_UNDERLINE).AsInteger())
				});
			}
			list[0].Position = position;
			foreach (int index in list2)
			{
				list[index].Underline = true;
			}
			foreach (KeyValuePair<int, int> keyValuePair in dictionary)
			{
				if (1 == keyValuePair.Value)
				{
					list[keyValuePair.Key].Superscript = true;
				}
				else if (2 == keyValuePair.Value)
				{
					list[keyValuePair.Key].Subscript = true;
				}
			}
			foreach (KeyValuePair<int, int> keyValuePair2 in dictionary2)
			{
				list[keyValuePair2.Key].Alignment = keyValuePair2.Value;
			}
			return list;
		}

		public bool DrawText(XYZ ptInsert, List<Page> pages, IDictionary<int, int> scripts, IDictionary<int, int> aligns, int length)
		{
			int num = this.GetViewPlanScale(this.m_doc);
			if (num <= 0)
			{
				num = 1;
			}
			ElementSet elementSet = new ElementSet();
			List<int> list = new List<int>();
			List<int> list2 = new List<int>();
			ICollection<Element> collection = new FilteredElementCollector(this.m_doc).OfClass(typeof(TextNoteType)).ToElements();
			XYZ xyz = XYZ.BasisX;
			XYZ xyz2 = XYZ.BasisY;
			SketchPlane sketchPlane = this.m_doc.ActiveView.SketchPlane;
			if (sketchPlane != null)
			{
				xyz = sketchPlane.GetPlane().XVec;
				xyz2 = sketchPlane.GetPlane().YVec;
			}
			if (TextTool._hWndRevit == null)
			{
                TextTool._hWndRevit = new WindowHandle(Process.GetCurrentProcess().MainWindowHandle);
			}
			ProgressBarForm progressBarForm = new ProgressBarForm(length, ProgressBarStyle.Blocks, true);
			progressBarForm.Show(TextTool._hWndRevit);
			foreach (Page page in pages)
			{
				foreach (Row row in page.m_rows)
				{
					double rowHeight = this.GetRowHeight(row);
					foreach (Text text in row.m_texts)
					{
						progressBarForm.RefreshProgressBar();
						if (progressBarForm.m_stopTag)
						{
							return false;
						}
						if (" " == text.Name || "\t" == text.Name || "\u3000" == text.Name)
						{
							Encoding encoding = Encoding.GetEncoding("iso-8859-1");
							text.Name = encoding.GetString(new byte[]
							{
								196
							});
							text.Font = "HY Arial Unicode MS v1";
						}
						else if ("\n" == text.Name)
						{
							Encoding encoding2 = Encoding.GetEncoding("iso-8859-1");
							text.Name = encoding2.GetString(new byte[]
							{
								197
							});
							text.Font = "HY Arial Unicode MS v1";
						}
                        TextAlignFlags textAlign = (TextAlignFlags)64;
						TextNote textNote = null;
						try
						{
							textNote = this.m_doc.GetTextNode(this.m_doc.ActiveView, text.Position, XYZ.BasisX, XYZ.BasisY, 0.01 * text.Height / 4.0, textAlign, text.Name);
						}
						catch
						{
							progressBarForm.Dispose();
							return false;
						}
						if (text.Underline)
						{
							list2.Add(list.Count);
							XYZ xyz3 = text.Position - xyz2 * (double)num * rowHeight / 304.8;
							XYZ xyz4 = xyz3 + xyz * (double)num * text.Width / 304.8;
							Line line = Line.CreateBound(xyz3, xyz4);
							DetailLine detailLine = this.m_doc.Create.NewDetailCurve(this.m_doc.ActiveView, line) as DetailLine;
							elementSet.Insert(detailLine);
						}
						elementSet.Insert(textNote);
						list.Add(textNote.Id.IntegerValue);
						XYZ xyz5 = RevitElementExtension.GetTextNoteCoord(textNote);
						if (text.Font.Contains("HY Arial"))
						{
							xyz5 += xyz2 * (double)num * text.Height / 2.0 / 304.8;
						}
						else if (text.Font.Contains("Arial"))
						{
							xyz5 += xyz2 * (double)num * text.Height / 6.0 / 304.8;
						}
						if (text.Superscript || text.Subscript)
						{
							xyz5 -= xyz2 * (double)num * (rowHeight - text.Height * 2.0) / 304.8;
						}
						else
						{
							xyz5 -= xyz2 * (double)num * (rowHeight - text.Height) / 304.8;
						}
						RevitElementExtension.SetTextNoteCoord(textNote, xyz5);
						TextNoteType textNoteType = this.GetCurrentTextNoteType(text, collection);
						if (textNoteType != null)
						{
							textNote.TextNoteType = textNoteType;
						}
						else
						{
							string font = text.Font;
							string text2 = Math.Round(text.Height, 1).ToString();
							int num2 = Common.RgbColorToInt(text.Color);
							string text3 = num2.ToString();
							string text4 = Convert.ToInt32(text.Bold).ToString();
							string text5 = Convert.ToInt32(text.Italic).ToString();
							string text6 = Convert.ToInt32(text.Underline).ToString();
							string text7 = string.Concat(new string[]
							{
								font,
								"_",
								text2,
								"_",
								text3,
								"_",
								text4,
								"_",
								text5,
								"_",
								text6
							});
							textNoteType = (textNote.TextNoteType.Duplicate(text7) as TextNoteType);
							textNoteType.get_Parameter(BuiltInParameter.TEXT_FONT).Set(text.Font);
							textNoteType.get_Parameter(BuiltInParameter.TEXT_SIZE).Set(text.Height / 304.8);
							textNoteType.get_Parameter(BuiltInParameter.LINE_COLOR).Set(num2);
							textNoteType.get_Parameter(BuiltInParameter.TEXT_STYLE_BOLD).Set(Convert.ToInt32(text.Bold));
							textNoteType.get_Parameter(BuiltInParameter.TEXT_STYLE_ITALIC).Set(Convert.ToInt32(text.Italic));
							textNoteType.get_Parameter(BuiltInParameter.TEXT_STYLE_UNDERLINE).Set(0);
							textNoteType.get_Parameter(BuiltInParameter.TEXT_WIDTH_SCALE).Set(0.7);
							textNoteType.get_Parameter(BuiltInParameter.LEADER_OFFSET_SHEET).Set(0);
							textNoteType.get_Parameter(BuiltInParameter.TEXT_BACKGROUND).Set(1);
							textNote.TextNoteType = textNoteType;
							collection.Add(textNoteType);
						}
					}
				}
			}
			this.m_doc.Regenerate();
			Group group = RevitVersionFuncs.NewGroup(this.m_doc, elementSet);
			if (!Article.g_Angle.Equals(0.0))
			{
				double num3 = AssistFunc.AngleToRadian(Article.g_Angle);
				XYZ xyz6 = ptInsert + this.m_doc.ActiveView.ViewDirection.Normalize();
				Line line2 = Line.CreateBound(ptInsert, xyz6);
				ElementTransformUtils.RotateElement(this.m_doc, group.Id, line2, num3);
			}
			SchemaBuilder schemaBuilder = new SchemaBuilder(Common.g_DataGuid);
			schemaBuilder.SetSchemaName("DataSchema");
			schemaBuilder.AddArrayField("Id", typeof(int));
			schemaBuilder.AddArrayField("Underline", typeof(int));
			schemaBuilder.AddMapField("Script", typeof(int), typeof(int));
			schemaBuilder.AddMapField("Align", typeof(int), typeof(int));
			schemaBuilder.AddSimpleField("Orientation", typeof(XYZ)).SetUnitType(0);
			Schema schema = schemaBuilder.Finish();
			Entity entity = new Entity(schema);
			Field field = schema.GetField("Id");
			entity.Set<IList<int>>(field, list);
			Field field2 = schema.GetField("Underline");
			entity.Set<IList<int>>(field2, list2);
			Field field3 = schema.GetField("Script");
			entity.Set<IDictionary<int, int>>(field3, scripts);
			Field field4 = schema.GetField("Align");
			entity.Set<IDictionary<int, int>>(field4, aligns);
			Field field5 = schema.GetField("Orientation");
            entity.Set<XYZ>(field5, ptInsert, (DisplayUnitType)3);
			group.SetEntity(entity);
			return true;
		}

		private TextNoteType GetCurrentTextNoteType(Text text, ICollection<Element> textNoteTypes)
		{
			foreach (Element element in textNoteTypes)
			{
				TextNoteType textNoteType = element as TextNoteType;
				string a = textNoteType.get_Parameter(BuiltInParameter.TEXT_FONT).AsString();
				double num = textNoteType.get_Parameter(BuiltInParameter.TEXT_SIZE).AsDouble();
				num = Math.Round(num * 304.8, 1);
				int num2 = textNoteType.get_Parameter(BuiltInParameter.LINE_COLOR).AsInteger();
				int num3 = Common.RgbColorToInt(text.Color);
				bool flag = Convert.ToBoolean(textNoteType.get_Parameter(BuiltInParameter.TEXT_STYLE_BOLD).AsInteger());
				bool flag2 = Convert.ToBoolean(textNoteType.get_Parameter(BuiltInParameter.TEXT_STYLE_ITALIC).AsInteger());
				Convert.ToBoolean(textNoteType.get_Parameter(BuiltInParameter.TEXT_STYLE_UNDERLINE).AsInteger());
				if (a == text.Font && num == text.Height && num2 == num3 && flag == text.Bold && flag2 == text.Italic)
				{
					return textNoteType;
				}
			}
			return null;
		}

		public void SetTextLocation(XYZ ptInsert, List<Page> pages)
		{
			XYZ xyz = ptInsert;
			double num = 0.0;
			double num2 = 0.0;
			int viewPlanScale = this.GetViewPlanScale(this.m_doc);
			XYZ xyz2 = XYZ.BasisX;
			XYZ xyz3 = XYZ.BasisY;
			SketchPlane sketchPlane = this.m_doc.ActiveView.SketchPlane;
			if (sketchPlane != null)
			{
				xyz2 = sketchPlane.GetPlane().XVec;
				xyz3 = sketchPlane.GetPlane().YVec;
			}
			foreach (Page page in pages)
			{
				foreach (Row row in page.m_rows)
				{
					XYZ xyz4 = xyz - num * (double)viewPlanScale * xyz3 / 304.8;
					foreach (Text text in row.m_texts)
					{
						if (Article.g_Format == 0)
						{
							text.Position = xyz4 + num2 * (double)viewPlanScale * xyz2 / 304.8;
							num2 += text.Width;
						}
						else if (1 == Article.g_Format)
						{
							text.Position = xyz4 - num * (double)viewPlanScale * xyz3 / 304.8;
							num += text.Height;
						}
						if (text.Subscript)
						{
							text.Position -= text.Height * (double)viewPlanScale * xyz3 / 304.8;
						}
					}
					if ("\n" == row.m_texts[row.m_texts.Count - 1].Name)
					{
						this.SetLocationOffset(row, num2 - row.m_texts[row.m_texts.Count - 1].Width);
					}
					else
					{
						this.SetLocationOffset(row, num2);
					}
					num2 = 0.0;
					double rowHeight = this.GetRowHeight(row);
					num = num + rowHeight + Article.g_RowInterval;
				}
				num = 0.0;
				if (Article.g_Format == 0)
				{
					xyz += xyz2 * (double)viewPlanScale * (Article.g_PageWidth + Article.g_PageInterval) / 304.8;
				}
				else if (1 == Article.g_Format)
				{
					xyz -= xyz3 * (double)viewPlanScale * (Article.g_PageHeight + Article.g_PageInterval) / 304.8;
				}
			}
		}

		private void SetLocationOffset(Row row, double rowWidth)
		{
			int viewPlanScale = this.GetViewPlanScale(this.m_doc);
			double num = Article.g_PageWidth - rowWidth;
			if (1 == row.m_align)
			{
				using (List<Text>.Enumerator enumerator = row.m_texts.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						Text text = enumerator.Current;
						text.Position += num * (double)viewPlanScale * XYZ.BasisX / 304.8;
					}
					return;
				}
			}
			if (2 == row.m_align)
			{
				foreach (Text text2 in row.m_texts)
				{
					text2.Position += num / 2.0 * (double)viewPlanScale * XYZ.BasisX / 304.8;
				}
			}
		}

		public List<Page> TransformRowToPage(List<Row> rows)
		{
			double num = 0.0;
			List<Page> list = new List<Page>();
			List<Row> list2 = new List<Row>();
			foreach (Row row in rows)
			{
				double rowHeight = this.GetRowHeight(row);
				num += rowHeight;
				if (num > Article.g_PageHeight)
				{
					Page item = new Page(list2);
					list.Add(item);
					list2 = new List<Row>();
					num = rowHeight;
				}
				num += Article.g_RowInterval;
				list2.Add(row);
			}
			if (list2.Count > 0)
			{
				Page item2 = new Page(list2);
				list.Add(item2);
			}
			return list;
		}

		private double GetRowHeight(Row row)
		{
			double num = 0.0;
			foreach (Text text in row.m_texts)
			{
				if (num < text.Height)
				{
					num = text.Height;
				}
			}
			return num;
		}

		public List<Row> TransformSectionToRow(List<Section> sections)
		{
			List<Row> list = new List<Row>();
			List<Text> list2 = new List<Text>();
			foreach (Section section in sections)
			{
				double num = 0.0;
				foreach (Text text in section.m_texts)
				{
					num += text.Width;
					if (num > Article.g_PageWidth)
					{
						Row item = new Row(list2, list2[0].Alignment);
						list.Add(item);
						list2 = new List<Text>();
						num = text.Width;
					}
					list2.Add(text);
				}
				if (list2.Count > 0)
				{
					Row item2 = new Row(list2, list2[0].Alignment);
					list.Add(item2);
					list2 = new List<Text>();
				}
			}
			return list;
		}

		public int GetViewPlanScale(Autodesk.Revit.DB.Document doc)
		{
			int result = -1;
			if (doc.ActiveView is ViewPlan)
			{
				result = (doc.ActiveView as ViewPlan).get_Parameter(BuiltInParameter.VIEW_SCALE).AsInteger();
			}
			else if (doc.ActiveView is ViewDrafting)
			{
				result = (doc.ActiveView as ViewDrafting).get_Parameter(BuiltInParameter.VIEW_SCALE).AsInteger();
			}
			else if (doc.ActiveView is View3D)
			{
				result = (doc.ActiveView as View3D).get_Parameter(BuiltInParameter.VIEW_SCALE).AsInteger();
			}
			else if (doc.ActiveView is ViewSheet)
			{
				result = (doc.ActiveView as ViewSheet).get_Parameter(BuiltInParameter.VIEW_SCALE).AsInteger();
			}
			else if (doc.ActiveView is ViewSection)
			{
				result = (doc.ActiveView as ViewSection).get_Parameter(BuiltInParameter.VIEW_SCALE).AsInteger();
			}
			return result;
		}

		public static double GetStringLength(string strInput)
		{
			if (string.IsNullOrEmpty(strInput))
			{
				return 0.0;
			}
			Encoding encoding = new ASCIIEncoding();
			double num = 0.0;
			byte[] bytes = encoding.GetBytes(strInput);
			for (int i = 0; i < bytes.Length; i++)
			{
				if (bytes[i] == 63)
				{
					num += 1.5;
				}
				else
				{
					num += 1.0;
				}
			}
			return num;
		}

		private Document m_doc;

        public static WindowHandle _hWndRevit;
	}
}
